package com.jindy.module.homepage.service.impl;

import com.jindy.common.constant.Constants;
import com.jindy.common.core.domain.AjaxResult;
import com.jindy.common.core.domain.entity.SysUser;
import com.jindy.common.core.domain.model.LoginUser;
import com.jindy.common.utils.SecurityUtils;
import com.jindy.module.approvalConfig.domain.ApprovalConfig;
import com.jindy.module.approvalConfig.mapper.ApprovalConfigMapper;
import com.jindy.module.approvalRecord.domain.ApprovalRecord;
import com.jindy.module.approvalRecord.service.IApprovalRecordService;
import com.jindy.module.customer.domain.Customer;
import com.jindy.module.customer.domain.CustomerFollow;
import com.jindy.module.customer.dto.CustomerDto;
import com.jindy.module.customer.mapper.CustomerFollowMapper;
import com.jindy.module.customer.mapper.CustomerMapper;
import com.jindy.module.customer.service.ICustomerService;
import com.jindy.module.homepage.service.HomepageService;
import com.jindy.module.homepage.vo.HomepageRespVO;
import com.jindy.module.homepage.vo.ModuleMessageCountVO;
import com.jindy.module.homepage.vo.SimpleKanbanInConditionVO;
import com.jindy.module.homepage.vo.SimpleKanbanInfoVO;
import com.jindy.module.logisticscost.service.LogisticsCostService;
import com.jindy.module.order.domain.Order;
import com.jindy.module.order.domain.OrderApprovalResult;
import com.jindy.module.order.mapper.OrderMapper;
import com.jindy.module.order.service.IOrderService;
import com.jindy.module.outboundorder.domain.OutboundOrder;
import com.jindy.module.outboundorder.service.IOutboundOrderService;
import com.jindy.module.returnapplyorder.domain.ReturnApply;
import com.jindy.module.returnapplyorder.dto.ReturnApplyDto;
import com.jindy.module.returnapplyorder.service.IReturnApplyService;
import com.jindy.module.statement.domain.AccountStatement;
import com.jindy.module.statement.mapper.AccountStatementMapper;
import com.jindy.module.transfer.domain.SyTransferT;
import com.jindy.module.transfer.domain.TransferApprovedResult;
import com.jindy.module.transfer.service.ISyTransferTService;
import com.jindy.system.service.ISysUserService;
import org.apache.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.jindy.common.constant.Constants.WU_LIU_DEPT_ID;

/**
 * 首页Service接口实现类
 *
 * @author zhaoxi
 * @date 2022-11-19
 */
@Service
public class HomepageServiceImpl implements HomepageService {

    @Resource
    private CustomerMapper customerMapper;

    @Resource
    private CustomerFollowMapper customerFollowMapper;

    @Resource
    private OrderMapper orderMapper;

    /**
     * 出库单
     */
    @Resource
    private IOutboundOrderService outboundOrderService;

    /**
     * 回货单
     */
    @Resource
    private IReturnApplyService returnApplyService;

    /**
     * 物流
     */
    @Resource
    private LogisticsCostService logisticsCostService;

    /**
     * 调拨
     */
    @Resource
    private ISyTransferTService syTransferTService;


    /**
     * 审批记录
     */
    @Resource
    private IApprovalRecordService approvalRecordService;

    /**
     * 查询人员信息
     */
    @Resource
    private ISysUserService userService;

    /**
     * 客户信息Service
     */
    @Resource
    private ICustomerService customerService;


    /**
     * 对账单Mapper
     */
    @Resource
    private AccountStatementMapper accountStatementMapper;

    /**
     * 配置信息表Mapper
     */
    @Resource
    private ApprovalConfigMapper approvalConfigMapper;

    @Override
    public HomepageRespVO selectHomepageRespVo(HomepageRespVO vo, CustomerDto dto, CustomerFollow follow, Order or) {

        //查询业务员客户数量
        dto.setChargePersonId(SecurityUtils.getUserId().toString());
        List<Customer> customerList1 = customerMapper.selectCustomerList(dto);
        Long customerCount1 = customerList1.stream().collect(Collectors.counting());

        //查询业务员客户跟进数量
        follow.setFollowUserId(SecurityUtils.getUserId().toString());
        List<CustomerFollow> customerFollowList1 = customerFollowMapper.selectCustomerFollowList(follow);
        Long customerFollowCount1 = customerFollowList1.stream().collect(Collectors.counting());

        //获取业务员订单条数
        or.setSalesman(SecurityUtils.getUserId());
        List<Order> orderList1 = orderMapper.selectOrderList(or);
        Long orderCount1 = orderList1.stream().collect(Collectors.counting());

        //遍历集合，找出已完成的订单放入list2
        List<Order> list2 = new ArrayList<>();
        orderList1.forEach(order->{
            if(order.getOrderStatus().equals("6")){
                list2.add(order);
            }
        });

        //该业务员所有已完成合同订单，总金额
        BigDecimal completedOrder = list2.stream().map(Order::getReceivables).reduce(BigDecimal.ZERO, BigDecimal::add);
        String strCompletedOrder = completedOrder.toString();
        //该业务员所有已完成合同订单，押金
        BigDecimal orderDeposit = list2.stream().map(Order::getDepositReceivable).reduce(BigDecimal.ZERO, BigDecimal::add);
        //该业务员所有已完成合同订单，未回款项
        BigDecimal num1 = new BigDecimal(strCompletedOrder);
        BigDecimal uncollectedAmount = num1.subtract(orderDeposit);

        vo.setCustomerCount(customerCount1);
        vo.setCustomerFollowCount(customerFollowCount1);
        vo.setOrderCount(orderCount1);
        vo.setOrderAmount(completedOrder);
        vo.setNotReceived(uncollectedAmount);
        return vo;
    }

    @Override
    public Map<String,Object> selectHomepage(Order or){
        Map<String, Object> mmap = customerMapper.selectHomepage(or);
        return mmap;

    }

    @Override
    public Map<String,Object> selectHomepageDay(Order or) {
        Map<String, Object> mmap = customerMapper.selectHomepageDay(or);
        return mmap;
    }

    @Override
    public Map<String,Object> selectHomepageWeek(Order or) {
        Map<String, Object> mmap = customerMapper.selectHomepageWeek(or);
        return mmap;
    }

    @Override
    public Map<String,Object> selectHomepageMonth(Order or) {
        Map<String, Object> mmap = customerMapper.selectHomepageMonth(or);
        return mmap;
    }

    @Override
    public Map<String,Object> selectHomepageYear(Order or) {
        Map<String, Object> mmap = customerMapper.selectHomepageYear(or);
        return mmap;
    }

    /**
     * 获取各个模块的待办数据
     * @param loginUser
     * @return
     */
    @Override
    public AjaxResult selectMessageCount(LoginUser loginUser) {

        ModuleMessageCountVO moduleMessageCountVO = new ModuleMessageCountVO();

        //获取物流待办信息
        getLogisticsCount(moduleMessageCountVO,loginUser);

        //获取个人中心
        getApproveCount(moduleMessageCountVO,loginUser);

        return AjaxResult.success(moduleMessageCountVO);
    }

    /**
     * 获取个人中心待办数量
     */
    private void getApproveCount(ModuleMessageCountVO moduleMessageCountVO,LoginUser loginUser) {
        ApprovalRecord approvalRecord = new ApprovalRecord();
        approvalRecord.setApprovalStatus(Constants.APPROVE);
        approvalRecord.setApproverId(loginUser.getUserId());
        List<ApprovalRecord> approvalRecords = approvalRecordService.selectApprovalRecordList(approvalRecord);
        moduleMessageCountVO.setApprovalCount(CollectionUtils.isEmpty(approvalRecords)?0:approvalRecords.size());
    }

    /**
     * 获取物流待办信息
     * @param moduleMessageCountVO
     */
    private void getLogisticsCount(ModuleMessageCountVO moduleMessageCountVO,LoginUser loginUser) {
        //判断是否是物流人员
        List<SysUser> wlList = userService.selectUserByDeptId(WU_LIU_DEPT_ID);
        List<Long> wlUserIdList = wlList.stream().map(SysUser::getUserId).collect(Collectors.toList());
        if (!wlUserIdList.contains(loginUser.getUserId())){
            return;
        }
        //获取物流管理代办数量
        //未完成出库物流数量
        OutboundOrder outboundOrder = new OutboundOrder();
        outboundOrder.setExpensesStatus("2");
        List<OutboundOrder> outboundOrders = outboundOrderService.selectOutboundOrderList(outboundOrder);
        Integer outboundOrderCount = CollectionUtils.isEmpty(outboundOrders)?0:outboundOrders.size();
        moduleMessageCountVO.setOutboundOrderCount(outboundOrderCount);

        //未完成回货物流数量
        ReturnApply returnApply = new ReturnApply();
        returnApply.setExpensesStatus("2");
        List<ReturnApplyDto> returnApplyList = returnApplyService.selectReturnApplyList(returnApply);
        Integer returnApplyCount = CollectionUtils.isEmpty(returnApplyList)?0:returnApplyList.size();
        moduleMessageCountVO.setReturnApplyCount(returnApplyCount);

        //出库物流费未填写
        List<OutboundOrder> outboundOrderList = outboundOrderService.getByOutboundNo(logisticsCostService.GetAllOutboundNo());
        Integer outboundOrderUnLogisticsCount = CollectionUtils.isEmpty(outboundOrderList)?0:outboundOrderList.size();
        moduleMessageCountVO.setOutboundOrderUnLogisticsCount(outboundOrderUnLogisticsCount);

        //回货物流费未填写
        List<ReturnApply> returnUnLogisticsList = returnApplyService.getByReturnNo(logisticsCostService.GetAllReturnNo());
        Integer returnUnLogisticsCount = CollectionUtils.isEmpty(returnUnLogisticsList)?0:returnUnLogisticsList.size();
        moduleMessageCountVO.setReturnUnLogisticsCount(returnUnLogisticsCount);

        //调拨
        SyTransferT syTransferT = new SyTransferT();
        syTransferT.setLogisticsStatus("0");
        List<TransferApprovedResult> transferList = syTransferTService.selectSyTransferTList(syTransferT);
        Integer transferLogisticsCount = CollectionUtils.isEmpty(transferList)?0:transferList.size();
        moduleMessageCountVO.setTransferLogisticsCount(transferLogisticsCount);

        //调拨物流未填写
        List<SyTransferT> syTransferNo = syTransferTService.getByOrderNo(logisticsCostService.GetAllTransferNo());
        Integer transferUnLogisticsCount = CollectionUtils.isEmpty(syTransferNo)?0:syTransferNo.size();
        moduleMessageCountVO.setTransferUnLogisticsCount(transferUnLogisticsCount);

        //获取物流管理代办数量
        Integer logisticsCount = outboundOrderCount+returnApplyCount+outboundOrderUnLogisticsCount
                +returnUnLogisticsCount+transferLogisticsCount+transferUnLogisticsCount;
        moduleMessageCountVO.setLogisticsCount(logisticsCount);
    }

    /**
     * 首页-简单看板-订单数据统计
     * @return
     */
    @Override
    public AjaxResult selectSimpleKanbanInfo(SimpleKanbanInConditionVO simpleKanbanInConditionVO) {
        //判断是否登录
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (Objects.isNull(loginUser)){
            return AjaxResult.error(HttpStatus.SC_FORBIDDEN,"请先登录");
        }
        //处理数据权限
        simpleKanbanInConditionVO = getPermission(simpleKanbanInConditionVO, loginUser);
        SimpleKanbanInfoVO simpleKanbanInfoVO = new SimpleKanbanInfoVO();
        //获取客户总数
        CustomerDto customerDto = new CustomerDto();
        customerDto.setChargePersonId(String.valueOf(simpleKanbanInConditionVO.getSalesmanId()));
        List<Customer> customerList = customerService.selectCustomerList(customerDto);
        simpleKanbanInfoVO.setCustomerNum(CollectionUtils.isEmpty(customerList)?0:customerList.size());
        //成交客户数
        Order order = new Order();
        order.setSalesman(simpleKanbanInConditionVO.getSalesmanId());
        List<OrderApprovalResult> orderApprovalResults = orderMapper.selectOrderApprovalList(order);
        int size = (int) customerList.stream().distinct().map(c ->
                        orderApprovalResults.stream()
                                .filter(s -> Objects.nonNull(c.getId())
                                        && Objects.nonNull(s.getCustomerId())
                                        && Objects.equals(c.getId(), String.valueOf(s.getCustomerId())))
                                .findAny().orElse(null))
                .filter(Objects::nonNull).count();
        simpleKanbanInfoVO.setDealCustomerNum(size);
        //订单数量
        List<OrderApprovalResult> orderResultList = orderMapper.selectOrderListByCondition(simpleKanbanInConditionVO);;
        simpleKanbanInfoVO.setOrderNum(CollectionUtils.isEmpty(orderResultList)?0:orderResultList.size());
        //订单押金
        BigDecimal receivedAmountSum = orderResultList.stream()
                .map(OrderApprovalResult::getReceivedAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        simpleKanbanInfoVO.setOrderAmountSum(receivedAmountSum);
        //已结算订单数量
        List<OrderApprovalResult> settledList = orderResultList.stream().filter(s -> "5".equals(s.getOrderStatus())).collect(Collectors.toList());
        simpleKanbanInfoVO.setSettledOrderCount(CollectionUtils.isEmpty(settledList)?0:settledList.size());

        //已结算订单金额
        List<String> numberList = settledList.stream().map(OrderApprovalResult::getOrderNo).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(numberList)){
            simpleKanbanInfoVO.setSettledOrderAmountSum(BigDecimal.ZERO);
        }else {
            List<AccountStatement> accountStatements = accountStatementMapper.selectAccountStatementListByNumbers(numberList);
            BigDecimal payAmountSum = accountStatements.stream()
                    .map(AccountStatement::getPayAmount)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            simpleKanbanInfoVO.setSettledOrderAmountSum(payAmountSum);
        }
        //查询预警订单
        List<Map<String,Object>> earlyWarningList = orderMapper.selectEarlyWarningOrder(simpleKanbanInConditionVO.getSalesmanId());
        if (!CollectionUtils.isEmpty(earlyWarningList)){
            //获取预警订单个数，逾期金额
            selectEarlyWarningOrder(earlyWarningList,simpleKanbanInfoVO);
        }else{
            simpleKanbanInfoVO.setWarningCount(0);
            simpleKanbanInfoVO.setOverdueAmount(BigDecimal.ZERO);
        }
        return AjaxResult.success(simpleKanbanInfoVO);
    }

    /**
     * 处理首页数据权限
     * @param simpleKanbanInConditionVO
     * @param loginUser
     * @return
     */
    private SimpleKanbanInConditionVO getPermission(SimpleKanbanInConditionVO simpleKanbanInConditionVO, LoginUser loginUser) {
        //业务员只能看自己的
        //胡总，余总，周总，财务部可以看所有人的
        if (Objects.isNull(simpleKanbanInConditionVO)){
            simpleKanbanInConditionVO =new SimpleKanbanInConditionVO();
            simpleKanbanInConditionVO.setSalesmanId(loginUser.getUserId());
        }else{
            //判断是否是超级管理员
            List<ApprovalConfig> configList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("SYKB-ADMIN", "1"));
            if (CollectionUtils.isEmpty(configList)) {
                throw new RuntimeException("请检查审批配置信息：SYKB-ADMIN");
            }
            List<Long> collect = configList.stream().map(ApprovalConfig::getUserId).collect(Collectors.toList());
            boolean isAdmin=false;
            for (Long userId : collect) {
                if (userId.equals(loginUser.getUserId())){
                    isAdmin=true;
                }
            }
            if (Objects.isNull(simpleKanbanInConditionVO.getSalesmanId())){
                simpleKanbanInConditionVO.setSalesmanId(loginUser.getUserId());
                //如果是超管理员
                if (isAdmin){
                    simpleKanbanInConditionVO.setSalesmanId(null);
                }
            }
        }
        return simpleKanbanInConditionVO;
    }

    /**
     * 时间转换
     * @param str
     * @return
     */
    public LocalDate stringToDate(String str){
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate date = LocalDate.parse(str, fmt);
        return date;
    }

    /**
     * 获取预警订单编号
     * @param earlyWarningList
     * @return
     */
    public void selectEarlyWarningOrder(List<Map<String,Object>> earlyWarningList,SimpleKanbanInfoVO simpleKanbanInfoVO) {
        //预计订单集合
        List<String> resultList = new ArrayList<>();
        //逾期订单集合
        List<String> overdueAmountOrderList = new ArrayList<>();
        //获取订单编号集
        List<String> orderNoList = new ArrayList<>();
        for (Map<String, Object> map : earlyWarningList) {
            orderNoList.add(map.get("orderNo").toString());
        }
        orderNoList = orderNoList.stream().distinct().collect(Collectors.toList());
        //时间使用日租金合计
        BigDecimal sum = BigDecimal.ZERO;
        //已收押金
        BigDecimal receivedAmount = BigDecimal.ZERO;
        //日租金合计
        BigDecimal totalDailyRent = BigDecimal.ZERO;
        //逾期金额
        BigDecimal overdueAmount = BigDecimal.ZERO;
        for (String orderNo : orderNoList) {
            for (Map<String, Object> map : earlyWarningList) {
                if (orderNo.equals(map.get("orderNo"))) {
                    //    获取入库时间
                    LocalDate warehouseTime = Objects.isNull(map.get("warehouseTime")) ? LocalDate.now() : stringToDate(map.get("warehouseTime").toString());
                    //获取出库时间
                    LocalDate logisticsTime = stringToDate(map.get("logisticsTime").toString());
                    //    获取日租金
                    BigDecimal dailyRent = new BigDecimal(map.get("dailyRent").toString());
                    long day = warehouseTime.toEpochDay() - logisticsTime.toEpochDay() + 1;
                    //   日租金*使用天数
                    sum = dailyRent.multiply(BigDecimal.valueOf(day)).add(sum);
                    receivedAmount = new BigDecimal(map.get("receivedAmount").toString());
                    totalDailyRent = new BigDecimal(map.get("totalDailyRent").toString());
                }
            }
            // 实际日租金合计*使用天数 >=已收押金-日租金合计*3 预警
            // 已收押金-日租金合计*3
            BigDecimal standardCost = receivedAmount.subtract(totalDailyRent.multiply(new BigDecimal("3")));
            if (sum.compareTo(standardCost) > 0) {
                resultList.add(orderNo);
                if (sum.subtract(receivedAmount).compareTo(BigDecimal.ZERO)>0){
                    overdueAmount = overdueAmount.add(sum.subtract(receivedAmount));
                    overdueAmountOrderList.add(orderNo);
                }
            }
        }
        simpleKanbanInfoVO.setWarningOrder(resultList);
        simpleKanbanInfoVO.setOverdueAmount(overdueAmount);
        simpleKanbanInfoVO.setWarningCount(resultList.size());
        simpleKanbanInfoVO.setOverdueAmountOrder(overdueAmountOrderList);
    }
}

